/*
 *
 * *******************************************************************
 *   @项目名称: BHex Android
 *   @文件名称: BaseTradeFragmentPresenter.java
 *   @Date: 1/9/19 5:13 PM
 *   @Author: chenjun
 *   @Description:
 *   @Copyright（C）: 2019 BlueHelix Inc.   All rights reserved.
 *   注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的.
 *  *******************************************************************
 *
 */

package io.bhex.app.trade.presenter;

import android.os.Bundle;
import android.text.TextUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import io.bhex.app.R;
import io.bhex.app.base.AppUI;
import io.bhex.app.trade.bean.BookListBean;
import io.bhex.app.trade.bean.WaitingShowBookList;
import io.bhex.app.trade.sort.BookListSort;
import io.bhex.app.utils.NetWorkStatus;
import io.bhex.app.utils.NumberUtils;
import io.bhex.app.view.BookView;
import io.bhex.app.view.bean.Book;
import io.bhex.baselib.mvp.BaseCoreActivity;
import io.bhex.baselib.mvp.BaseFragmentPresenter;
import io.bhex.baselib.utils.DebugLog;
import io.bhex.baselib.utils.ToastUtils;
import io.bhex.sdk.account.UserInfo;
import io.bhex.sdk.data_manager.NetWorkApiManager;
import io.bhex.sdk.quote.QuoteApi;
import io.bhex.sdk.quote.bean.CoinPairBean;
import io.bhex.sdk.quote.bean.DepthDataBean;
import io.bhex.sdk.quote.bean.DepthSocketResponse;
import io.bhex.sdk.quote.bean.TickerBean;
import io.bhex.sdk.quote.bean.TickerListBean;
import io.bhex.sdk.socket.NetWorkObserver;
import io.bhex.sdk.trade.bean.OrderBean;


public abstract class BaseTradeFragmentPresenter<V extends BaseTradeFragmentPresenter.BaseTradeFragmentUI> extends BaseFragmentPresenter<V> {

    private BookDataHandleTask bookDataHandleTask;
    //盘口数据队列
    private LinkedBlockingQueue<DepthDataBean> depthDataQueue = new LinkedBlockingQueue<>();
    private boolean isResub;    //重新发起了订阅
    private DisplayBookTask displayTask;

    public interface BaseTradeFragmentUI extends AppUI {

        void showOpenOrders(List<OrderBean> datas);

        void showHistoryOrders(List<OrderBean> datas);

        String getExchangeId();

        String getSymbols();

        String getQuoteToken();

        String getBaseToken();

        void showLatestPrice(TickerBean data);

        /**
         * 更新交易界面资产信息
         *
         * @param token
         * @param asset
         */
        void updateAssettByToken(String token, String asset);

        void resetView();

        String getDigitStr();

        void createOrderSuccess();

        void loadMoreComplete();

        void loadMoreFailed();

        void loadEnd();

        boolean isSelected();

        void showSocketError(String error);

        int getDigitBase();

        List<BookListBean> getBookListData();

        void updateBookList();

        boolean isCurrentAskOrderPrice(String priceStr);

        boolean isCurrentBidOrderPrice(String priceStr);

        boolean isShowCumulativeVolume();
    }

    private static final String LOGTAG = "BaseTradeFragmentPresenter";
    //当前Fragment是否可见
    protected boolean isVisible;

    protected List<OrderBean> currentOrders = new ArrayList<>();
    protected List<OrderBean> historyOrders = new ArrayList<>();

    protected DepthDataBean currentDepthData;
    protected String mPageId = "";


    public void getTicker() {
        if (!isVisible) {
            return;
        }

        QuoteApi.SubTicker(getUI().getExchangeId(), getUI().getSymbols(), new NetWorkObserver<TickerListBean>() {
            @Override
            public void onShowUI(TickerListBean response) {
                if (getUI() == null || !getUI().isAlive() || response == null)
                    return;

                List<TickerBean> datas = response.getData();
                if (datas != null) {
                    for (TickerBean data : datas) {
                        String s = data.getS();
                        if (!TextUtils.isEmpty(s)) {
                            if (s.equals(getUI().getSymbols())) {
                                getUI().showLatestPrice(data);
                            }
                        }
                    }
                }
            }

            @Override
            public void onError(String error) {
            }
        });
    }

    private long depthDataId = 0l;

    public void requestDepthData() {
        if (!isVisible) {
            return;
        }
        clearDataQueue();
        isResub = true;
        startBookTask();
        QuoteApi.SubDepthData(getUI().getExchangeId(), getUI().getSymbols(), new NetWorkObserver<DepthSocketResponse>() {
            @Override
            public synchronized void onShowUI(DepthSocketResponse response) {
                if (getUI() == null || !getUI().isAlive() || response == null)
                    return;

                if (response.data != null && response.data.size() > 0)
                    if (response.data.get(0) != null) {
                        boolean bFirst = true;
                        if (response.f != null) {
                            bFirst = response.f;
                        }
                        if (isResub) {
                            if (!bFirst) {
                                //重新发起了订阅，如果非首次推送到达的全量数据(有可能是推送到达延迟的旧数据)，直接丢弃非全量垃圾数据
                                return;
                            } else {
                                clearDataQueue();
                                isResub = false;
                            }
                        }

                        DepthDataBean depthData = response.data.get(0);
                        depthData.setId(depthDataId++);
                        if (!TextUtils.isEmpty(response.symbol)) {
                            // socket  返回depthData  s 币对未赋值，所以需要手动赋值
                            depthData.setS(response.symbol);
                        }
                        currentDepthData = depthData;

                        handleAndShowDepth(depthData, bFirst);

                    }
            }

            @Override
            public void onError(String error) {
                getUI().showSocketError(error);
            }
        });

//        addTestData();

    }

    long oId = 0;

    /**
     * 添加测试数据
     */
    private void addTestData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
//                synchronized (this){
                    DebugLog.e("THREAD-addTestData",Thread.currentThread().getName() + " "+Thread.currentThread().getId());
                    for (int i = 1; i <= 500000; i++) {

                        DepthDataBean depthDataBean = new DepthDataBean();
                        depthDataBean.setId(depthDataId++);
                        depthDataBean.setO(oId++);
                        depthDataBean.setS("BTCUSDT");

                        Random random = new Random();
                        List<List<String>> b = new ArrayList<>();
                        List<List<String>> a = new ArrayList<>();

                        for (int j = 1; j <= 1; j++) {

                            List<String> aItem = new ArrayList<>();
                            aItem.add((110 + i+j) + "");
                            aItem.add(random.nextInt(100) + "");
                            a.add(aItem);
                            if (i >= 10) {
                                List<String> aRemoveItem = new ArrayList<>();
                                aRemoveItem.add((110 + i + j - 10) + "");
                                aRemoveItem.add(0 + "");
                                a.add(aRemoveItem);
                            }
                        }

                        for (int k = 0; k < 1; k++) {

                            List<String> bItem = new ArrayList<>();
                            bItem.add((100 + i + k) + "");
                            bItem.add(random.nextInt(100) + "");
                            b.add(bItem);
                            if (i >= 10) {
                                List<String> bRemoveItem = new ArrayList<>();
                                bRemoveItem.add((100 + i + k - 10) + "");
                                bRemoveItem.add(0 + "");
                                b.add(bRemoveItem);
                            }
                        }
                        depthDataBean.setB(b);
                        depthDataBean.setA(a);
//            depthDataBean.setT(depthData.getT());
                        currentDepthData = depthDataBean;

                        handleAndShowDepth(depthDataBean, false);

                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
//                }
            }
        }).start();

    }


    public void resetAllData(CoinPairBean coinPairBeanParam) {
        clearDataQueue();
        if (currentOrders != null) {
            currentOrders.clear();
            getUI().showOpenOrders(currentOrders);
        }
        if (historyOrders != null) {
            historyOrders.clear();
            getUI().showHistoryOrders(historyOrders);
        }
        getCurrentEntrustOrders();
        getHistoryEntrustOrders(false);

        getUI().resetView();
        getAssetList(getUI().getQuoteToken());
        getAssetList(getUI().getBaseToken());
        subSymbolOrder();

        //QuoteApi.UnSubTickers();
        //QuoteApi.UnSubDepthData();

        getTicker();
        requestDepthData();
    }

    /**
     * 改变盘口数量显示模式
     * @param isShowCumulativeVolume 是否以累计数量模式 >>> 显示盘口
     */
    public void changeBookQuantityShowMode(boolean isShowCumulativeVolume) {
        reSubDepth();
    }

    /**
     * 合并book列表小数
     *
     * @param digitDepth
     */
    public void changeMergeDigit(String digitDepth) {
        //改变深度合并位数，如果队列有数据，不能直接加入队列,只需赋值小数位数，下次数据合并会自动处理
        reSubDepth();
//        if (currentDepthData != null) {
//            if (depthDataQueue.isEmpty()) {
//                handleAndShowDepth(currentDepthData, false);
//            }
//        }
    }

    public void refresh() {

        if (!UserInfo.isLogin()) {
            //未登录状态不请求
            return;
        } else {
            if (!NetWorkStatus.isConnected(getActivity())) {
                ToastUtils.showShort(getActivity(), getResources().getString(R.string.hint_network_not_connect));
                return;
            }
            getAssetList(getUI().getQuoteToken());
            getAssetList(getUI().getBaseToken());
            getAsset(getUI().getQuoteToken());
            getAsset(getUI().getBaseToken());
            getCurrentEntrustOrders();
            getHistoryEntrustOrders(false);
        }
    }


    public void loadMore() {
        getHistoryEntrustOrders(true);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DebugLog.e(LOGTAG, "ON onCreate");
    }

    @Override
    public void onUIReady(BaseCoreActivity activity, V ui) {
        super.onUIReady(activity, ui);
        DebugLog.e(LOGTAG, "ON onUIReady");
    }

    @Override
    public void onResume() {
        super.onResume();
        getCurrentEntrustOrders();
        getHistoryEntrustOrders(false);
//        sourceMapA.clear();
//        sourceMapB.clear();
        sourceMapA = new TreeMap<>();
        sourceMapB = new TreeMap<>();
        getUI().resetView();

        getAssetList(getUI().getQuoteToken());
        getAssetList(getUI().getBaseToken());
        subSymbolOrder();
        if (getUI().isSelected() && isVisible) {
            getTicker();
            requestDepthData();
        }
    }

    @Override
    public void onVisibleChanged(boolean visible) {
        super.onVisibleChanged(visible);
        isVisible = visible;
        DebugLog.e("XXXXX", this.toString() + "  " + isVisible + "  isSelected " + getUI().isSelected());
        if (getUI().isSelected()) {
            if (isVisible) {
                getTicker();
                startBookTask();
                requestDepthData();
            } else {
                stopTask();
                QuoteApi.UnSubTickers();
                QuoteApi.UnSubDepthData();

            }
        }

        if (!TextUtils.isEmpty(getUI().getQuoteToken())) {
            getAsset(getUI().getQuoteToken());
        }
        if (!TextUtils.isEmpty(getUI().getBaseToken())) {
            getAsset(getUI().getBaseToken());
        }

    }

    /**
     * 处理并展示深度数据
     *
     * @param depthDataBean
     */
    private void handleAndShowDepth(DepthDataBean depthDataBean, boolean f) {
        depthDataBean.f = f;
        if (TextUtils.isEmpty(depthDataBean.getS()) || getUI() == null || !getUI().isAlive() || depthDataBean == null || TextUtils.isEmpty(getUI().getSymbols())) {
            return;
        }
        if (!isVisible || !depthDataBean.getS().equals(getUI().getSymbols())) {
            return;
        }

        addDataQueue(depthDataBean);

    }

    /**
     * 添加盘口数据对象到队列
     *
     * @param depthDataBean
     */
    private void addDataQueue(DepthDataBean depthDataBean) {
        //添加盘口数据对象到队列
        try {
            if (depthDataBean != null) {
//                if (depthDataQueue.size()> AppData.TICKER.DEPTH_MAX_QUEUE_WATING_COUNT) {
//                    reSubDepth();
//                }else{
                    DebugLog.e("DepthData", "QUEUE add data " + depthDataBean.getId() + "  " + depthDataBean.getS());
                depthDataQueue.put(depthDataBean);
//                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 重新订阅深度数据
     */
    private void reSubDepth() {
        clearDataQueue();
        requestDepthData();
    }

    /**
     * 清理队列数据
     */
    private void clearDataQueue() {
        if (depthDataQueue != null) {
            depthDataQueue.clear();
        }
        if (displayQueue != null) {
            displayQueue.clear();
        }
    }

    /**
     * 开启队列处理数据
     */
    private void startBookTask() {
//        bookDataHandleTask = new BookDataHandleTask();
//        bookDataHandleTask.start();
//        displayTask = new DisplayBookTask();
//        displayTask.start();
        if (bookDataHandleTask == null || !bookDataHandleTask.isAlive() || bookDataHandleTask.isInterrupted()) {
            bookDataHandleTask = new BookDataHandleTask();
            bookDataHandleTask.start();
        }
        if (displayTask == null || !displayTask.isAlive() || displayTask.isInterrupted()) {
            displayTask = new DisplayBookTask();
            displayTask.start();
        }
    }

    private void stopTask(){
        if (bookDataHandleTask != null) {
            if (!bookDataHandleTask.isInterrupted()) {
                bookDataHandleTask.interrupt();
            }
        }
        if (displayTask != null) {
            if (!displayTask.isInterrupted()) {
                displayTask.interrupt();
            }
        }
    }

    //book默认条数
    private static final int BOOK_LIST_DEFAULT_NUM = 10;

    private class BookDataHandleTask extends Thread {

        @Override
        public void run() {

            excuteQueueTask();
        }
    }

    private ArrayBlockingQueue<WaitingShowBookList> displayQueue = new ArrayBlockingQueue<WaitingShowBookList>(100);

    private class DisplayBookTask extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                WaitingShowBookList waitingShowBookList = null;
                while ((waitingShowBookList = displayQueue.take()) != null && isVisible) {
//                    String threadInfo = Thread.currentThread().getName()+"  " + Thread.currentThread().getId();
//                    DebugLog.e("DepthData-diffDepth-Thread", threadInfo +" displayQueue handling " + waitingShowBookList.getId());
                    List<Book> askBooks = waitingShowBookList.getAskBooks();
                    List<Book> bidBooks = waitingShowBookList.getBidBooks();

                    List<BookListBean> bookListData = getUI().getBookListData();
                    for (int askIndex = BOOK_LIST_DEFAULT_NUM; askIndex > 0; askIndex--) {
                        BookListBean bookListBean = bookListData.get(askIndex - 1);
                        bookListBean.setBook(askBooks.get(BOOK_LIST_DEFAULT_NUM - askIndex));
                    }

                    for (int bidIndex = BOOK_LIST_DEFAULT_NUM + 1; bidIndex < BOOK_LIST_DEFAULT_NUM * 2 + 1; bidIndex++) {
                        BookListBean bookListBean = bookListData.get(bidIndex);
                        bookListBean.setBook(bidBooks.get(bidIndex - BOOK_LIST_DEFAULT_NUM - 1));
                    }

                    //币对相同才会更新盘口
                    if (waitingShowBookList.getSymbol().equals(getUI().getSymbols())) {
//                        DebugLog.e("Depth-COUNT-diffDepth", "Depth update " + headerData.getId() + "  " + headerData.getS()+ " serverId = "+headerData.getO());
                        getUI().updateBookList();

                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 执行深度队列任务
     */
    private void excuteQueueTask() {
        try {

//            DebugLog.e("excuteQueueTask-DepthData-diffDepth", "QUEUE wating size >>>   " + depthDataQueue.size() + "  Thread name = " + Thread.currentThread().getName() + "  " + Thread.currentThread().getId());
            DepthDataBean headerData = null;
            //循环队列，取出头部元素
            while ((headerData = depthDataQueue.take()) != null && isVisible) {
//                  headerData = depthDataQueue.take(); //移除并返问队列头部的元素  如果队列为空，则阻塞
                if (headerData != null) {
                    DebugLog.e("excuteQueueTask-DepthData-diffDepth", "QUEUE wating size >>>   " + depthDataQueue.size() + "  Thread name = " + Thread.currentThread().getName() + "  " + Thread.currentThread().getId());
//                        DebugLog.e("DepthData-diffDepth", "QUEUE handle start " + headerData.getId() + "  " + headerData.getS() + " serverId = " + headerData.getO());
                    String digitStr = getUI().getDigitStr();
                    int digitCount = NumberUtils.calNumerCount(getActivity(), digitStr);

                    if (headerData.f == true) {
//                        sourceMapA.clear();
//                        sourceMapB.clear();

                        sourceMapA = new TreeMap<>();
                        sourceMapB = new TreeMap<>();
                    }

                    List<List<String>> ask;
                    List<List<String>> bit;

                    //返回A B 异常数据处理
                    if (headerData.getA() == null) {
                        ask = new ArrayList<>();
                    } else {
                        ask = headerData.getA();
                    }

                    if (headerData.getB() == null) {
                        bit = new ArrayList<>();
                    } else {
                        bit = headerData.getB();
                    }

                    headerData.setA(ask);
                    headerData.setB(bit);

                    //排序压缩合并后的全量数据

                    //卖盘增量数据
                    List<List<String>> a = headerData.getA();   //由小到大
                    for (List<String> result : a) {
                        //异常数据处理（该档位数量为空，自动补零）
                        BigDecimal quantity = TextUtils.isEmpty(result.get(1)) ? BigDecimal.ZERO : new BigDecimal(result.get(1));
//                            DebugLog.e("DepthData-A", result.get(1) + "  " + Float.valueOf(result.get(1)));
                        if (quantity.compareTo(BigDecimal.ZERO) > 0) {
                            //新增价档位/者该价格档位数量更新
                            sourceMapA.put(result.get(0), result.get(1));
                        } else {
                            //移除档位（该价格档位挂单数量为零）
                            sourceMapA.remove(result.get(0));
                        }
                    }

                    //买盘增量数据
                    List<List<String>> b = headerData.getB();   //由小到大
                    for (List<String> result : b) {
                        //异常数据处理（该档位数量为空，自动补零）
                        BigDecimal quantity = TextUtils.isEmpty(result.get(1)) ? BigDecimal.ZERO : new BigDecimal(result.get(1));
//                            DebugLog.e("DepthData-B", result.get(1) + "  " + Float.valueOf(result.get(1)));
                        if (quantity.compareTo(BigDecimal.ZERO) > 0) {
                            //新增价档位/者该价格档位数量更新
                            sourceMapB.put(result.get(0), result.get(1));
                        } else {
                            //移除档位（该价格档位挂单数量为零）
                            sourceMapB.remove(result.get(0));
                        }
                    }

                    //卖盘全量数据-精度(小数位)合并
                    Map<String, String> mergeDataMapOfA = new TreeMap<>(new BookListSort());
                    for (String key : sourceMapA.keySet()) {
//                        DebugLog.e("DIGIT", "原始：" + key);
                        String newKey = NumberUtils.roundUpString(key, digitCount);
//                        DebugLog.e("DIGIT", "处理：" + newKey);
                        BigDecimal sourceQuantiy = new BigDecimal(sourceMapA.get(key));
                        String mergeQuantityStr = mergeDataMapOfA.get(newKey);
                        BigDecimal mergeQuantity = new BigDecimal(TextUtils.isEmpty(mergeQuantityStr) ? "0" : mergeQuantityStr);
                        String newQuantity = mergeQuantity.add(sourceQuantiy).toPlainString();//累计合并挂单数量（当前价档位对应的累加挂单量）
                        mergeDataMapOfA.put(newKey, newQuantity);
                    }

                    //买盘全量数据-精度(小数位)合并
                    Map<String, String> mergeDataMapOfB = new TreeMap<>(new BookListSort());
                    for (String key : sourceMapB.keySet()) {
//                      DebugLog.e("DIGIT", "原始：" + key);
                        String newKey = NumberUtils.roundDownString(key, digitCount);
//                      DebugLog.e("DIGIT", "处理：" + newKey);
                        BigDecimal sourceQuantiy = new BigDecimal(sourceMapB.get(key));
                        String mergeQuantityStr = mergeDataMapOfB.get(newKey);
                        BigDecimal mergeQuantity = new BigDecimal(TextUtils.isEmpty(mergeQuantityStr) ? "0" : mergeQuantityStr);
                        String newQuantity = mergeQuantity.add(sourceQuantiy).toPlainString();//累计合并挂单数量（当前价档位对应的累加挂单量）
                        mergeDataMapOfB.put(newKey, newQuantity);
                    }

                    //TODO 待定数据
                    List<List<String>> A = new ArrayList<>();
                    for (String key : mergeDataMapOfA.keySet()) {
                        ArrayList<String> item = new ArrayList<>();
                        item.add(key);
                        item.add(mergeDataMapOfA.get(key));
                        A.add(item);
                    }
//                    headerData.setA(A);

                    List<List<String>> B = new ArrayList<>();
                    for (String key : mergeDataMapOfB.keySet()) {
                        ArrayList<String> item = new ArrayList<>();
                        item.add(key);
                        item.add(mergeDataMapOfB.get(key));
                        B.add(item);
                    }
//                    headerData.setB(B);


                    /**开始准备待显示数据******/

                    //阴影比例计算公式：成交金额/[展示买平均值+展示卖平均值）/2]%

                    //截取卖盘--显示档位所需数据-asks
                    List<List<String>> resultA = new ArrayList<>();
                    for (int i = 0; i < A.size(); i++) {
                        if (i < BOOK_LIST_DEFAULT_NUM) {
                            resultA.add(A.get(i));  //TODO 由 小 --> 大
                        }
                    }

                    BigDecimal totalADeal = BigDecimal.ZERO;
                    for (List<String> item : resultA) {
                        String priceStr = item.get(0);
                        String amountStr = item.get(1);
//                        BigDecimal price = new BigDecimal(TextUtils.isEmpty(priceStr) ? "0" : priceStr);
                        BigDecimal amount = new BigDecimal(TextUtils.isEmpty(amountStr) ? "0" : amountStr);

                        totalADeal = totalADeal.add(amount);    //卖盘累加挂单量

                    }

                    //截取显示档位所需数据-bid
                    List<List<String>> resultB = new ArrayList<>();
                    for (int i = B.size() - 1; i >= 0; i--) {   //TODO  B 倒序装载数据
                        if (i >= B.size() - BOOK_LIST_DEFAULT_NUM) {
                            resultB.add(B.get(i));  //TODO 由 大 --> 小
                        }
                    }

                    BigDecimal totalBDeal = BigDecimal.ZERO;
                    for (int i = resultB.size() - 1; i >= 0; i--) {
                        List<String> item = resultB.get(i);
                        String priceStr = item.get(0);
                        String amountStr = item.get(1);

                        // BigDecimal price = new BigDecimal(TextUtils.isEmpty(priceStr) ? "0" : priceStr);
                        BigDecimal amount = new BigDecimal(TextUtils.isEmpty(amountStr) ? "0" : amountStr);

                        totalBDeal = totalBDeal.add(amount);

                    }

                    //买盘或者卖盘最大累加挂单数量
                    BigDecimal maxDealQuantity = totalADeal.compareTo(totalBDeal) > 0 ? totalADeal : totalBDeal;


                    List<Book> bidBooks = new ArrayList<>();
                    List<Book> askBooks = new ArrayList<>();

                    //准备卖盘待显示数据
                    BigDecimal currentTotalAmountOfA = BigDecimal.ZERO;    //当前卖盘数量累积挂单量
                    for (List<String> item : resultA) { //TODO resultA 由 小 --> 大
                        String priceStr = item.get(0);
                        String amountStr = item.get(1);
//                        BigDecimal price = new BigDecimal(TextUtils.isEmpty(priceStr) ? "0" : priceStr);
                        BigDecimal amount = new BigDecimal(TextUtils.isEmpty(amountStr) ? "0" : amountStr);

                        Book book1 = new Book();
                        book1.setBid(false);
                        book1.setPrice(priceStr);
                        book1.setPriceColor(getResources().getColor(R.color.red));
                        book1.setVolume(io.bhex.baselib.utils.NumberUtils.handVolumeLength(amountStr, getUI().getDigitBase()));
                        book1.setProgressColor(getResources().getColor(R.color.red20));
                        currentTotalAmountOfA = currentTotalAmountOfA.add(amount);
                        book1.setCumulativeVolume(io.bhex.baselib.utils.NumberUtils.handVolumeLength(currentTotalAmountOfA.toPlainString(), getUI().getDigitBase()));
                        float progress = 0l;
                        if (maxDealQuantity.compareTo(BigDecimal.ZERO) != 0) {
                            progress = currentTotalAmountOfA.divide(maxDealQuantity, 2, BigDecimal.ROUND_UP).floatValue();
                        }
                        // DebugLog.w("PROGress","A "+progress);
                        book1.setProgress(progress);
                        book1.setProgressMode(BookView.PROGRESS_RIGHT_MODE);
                        book1.setHasOrderMarked(getUI().isCurrentAskOrderPrice(priceStr));
                        book1.setShowCumulativeVolume(getUI().isShowCumulativeVolume());
                        askBooks.add(book1);
                    }

                    //补齐卖盘（如果数据不足）
                    if (BOOK_LIST_DEFAULT_NUM > askBooks.size()) {
                        int size = askBooks.size();
                        for (int i = 0; i < BOOK_LIST_DEFAULT_NUM - size; i++) {
                            Book book1 = new Book();
                            book1.setBid(false);
                            book1.setPrice("--");
                            book1.setPriceColor(getResources().getColor(R.color.red));
                            book1.setVolume("--");
                            book1.setCumulativeVolume("--");
                            book1.setProgressColor(getResources().getColor(R.color.red20));
                            book1.setProgress(0f);
                            book1.setProgressMode(BookView.PROGRESS_RIGHT_MODE);
                            book1.setHasOrderMarked(false);
                            book1.setShowCumulativeVolume(getUI().isShowCumulativeVolume());
                            askBooks.add(book1);
                        }
                    }

                    //准备买盘待显示数据
                    BigDecimal currentTotalAmountOfB = BigDecimal.ZERO;    //当前数量累积量
//                        for (int i = resultB.size() - 1; i >= 0; i--) { //TODO resultB 由 大 --> 小
                    for (List<String> item : resultB) { //TODO resultB 由 大 --> 小
                        String priceStr = item.get(0);
                        String amountStr = item.get(1);
//                        BigDecimal price = new BigDecimal(TextUtils.isEmpty(priceStr) ? "0" : priceStr);
                        BigDecimal amount = new BigDecimal(TextUtils.isEmpty(amountStr) ? "0" : amountStr);

                        Book book1 = new Book();
                        book1.setBid(true);
                        book1.setPrice(priceStr);
                        book1.setPriceColor(getResources().getColor(R.color.green));
                        book1.setVolume(io.bhex.baselib.utils.NumberUtils.handVolumeLength(amountStr, getUI().getDigitBase()));
                        book1.setProgressColor(getResources().getColor(R.color.green20));
                        currentTotalAmountOfB = currentTotalAmountOfB.add(amount);
                        book1.setCumulativeVolume(io.bhex.baselib.utils.NumberUtils.handVolumeLength(currentTotalAmountOfB.toPlainString(), getUI().getDigitBase()));
                        float progress = 0l;
                        if (maxDealQuantity.compareTo(BigDecimal.ZERO) != 0) {
                            progress = currentTotalAmountOfB.divide(maxDealQuantity, 2, BigDecimal.ROUND_UP).floatValue();
                        }
                        //            DebugLog.w("PROGress","B "+progress);
                        book1.setProgress(progress);
                        book1.setProgressMode(BookView.PROGRESS_RIGHT_MODE);
                        book1.setHasOrderMarked(getUI().isCurrentBidOrderPrice(priceStr));
                        book1.setShowCumulativeVolume(getUI().isShowCumulativeVolume());
                        bidBooks.add(book1);
                    }

                    //补齐买盘（如果数据不足）
                    if (BOOK_LIST_DEFAULT_NUM > bidBooks.size()) {
                        int size = bidBooks.size();
                        for (int i = 0; i < BOOK_LIST_DEFAULT_NUM - size; i++) {
                            Book book1 = new Book();
                            book1.setBid(true);
                            book1.setPrice("--");
                            book1.setPriceColor(getResources().getColor(R.color.green));
                            book1.setVolume("--");
                            book1.setCumulativeVolume("--");
                            book1.setProgressColor(getResources().getColor(R.color.green20));
                            book1.setProgress(0f);
                            book1.setProgressMode(BookView.PROGRESS_RIGHT_MODE);
                            book1.setHasOrderMarked(false);
                            book1.setShowCumulativeVolume(getUI().isShowCumulativeVolume());
                            bidBooks.add(book1);
                        }
                    }

                    String askPrice1 = askBooks.get(0).getPrice();
                    String bidPrice1 = bidBooks.get(0).getPrice();

//                        DebugLog.e("DepthData-diffDepth", "QUEUE handle end   " + headerData.getId() + "  " + headerData.getS() + " serverId = " + headerData.getO());

                    if (askBooks.size()>0 && bidBooks.size() >0 && askPrice1.equals("--") && bidPrice1.equals("--") && NumberUtils.sub(bidPrice1, askPrice1) >= 0) { //TODO askBooks.size()>0 && bidBooks.size() >0  && askPrice1.equals("--") && bidPrice1.equals("--") 排除空盘可能
                        //异常价格盘口
//                        DebugLog.e("DepthData-diffDepth", "socket QUEUE handle price exception >>>>> " + headerData.getId() + " serverId = " + headerData.getO() + "  ask1 = " + askPrice1 + "  bid1 = " + bidPrice1);
//                        if (BuildConfig.DEBUG) {
//                            ToastUtils.showShort("price exception >>>>> " + headerData.getId() + " serverId = " + headerData.getO() + "  ask1 = " + askPrice1 + "  bid1 = " + bidPrice1);
//                            LogToFile.e("DEPTH-DATA-EXCEPTION-ASK-ALL", Convert.formatJson(sourceMapA));
//                            LogToFile.e("DEPTH-DATA-EXCEPTION-BID-ALL", Convert.formatJson(sourceMapB));
//                            LogToFile.e("DEPTH-DATA-EXCEPTION-ASK", Convert.formatJson(askBooks));
//                            LogToFile.e("DEPTH-DATA-EXCEPTION-BID", Convert.formatJson(bidBooks));
//                        }
                        getActivity().runOnUiThread(() -> {
                            reSubDepth();
                        });
                    } else {
                        try {
                            WaitingShowBookList waitingShowBookList = new WaitingShowBookList();
                            waitingShowBookList.setId(headerData.getO());
                            waitingShowBookList.setSymbol(headerData.getS());
                            waitingShowBookList.setAskBooks(askBooks);
                            waitingShowBookList.setBidBooks(bidBooks);
                            if (displayQueue == null) {
                                displayQueue = new ArrayBlockingQueue<WaitingShowBookList>(100);
                                displayQueue.put(waitingShowBookList);
                            } else {
                                displayQueue.put(waitingShowBookList);    //添加一个元素并返回true 如果队列已满，则返回false
                            }
                            DebugLog.e("DepthData-diffDepth", "displayQueue size = " + displayQueue.size() + " " + headerData.getId() + "  " + headerData.getS() + " serverId = " + headerData.getO());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取资产列表
     *
     * @param token
     */
    abstract protected void getAssetList(final String token);

    abstract protected void subSymbolOrder();

    /**
     * 获取资产
     *
     * @param tokenId
     */
    abstract protected void getAsset(final String tokenId);

    /**
     * 获取当前委托
     */
    abstract protected void getCurrentEntrustOrders();

    /**
     * 获取历史委托
     */
    abstract public void getHistoryEntrustOrders(boolean isLoadMore);


    /**
     * 下单
     *
     * @param isBuyMode
     * @param isLimitedPrice
     * @param exchangeId
     * @param symbol
     * @param price
     * @param amount
     */
    abstract public void createOrder(boolean isBuyMode, boolean isLimitedPrice, String exchangeId, String symbol, String price, String amount);


    /**
     * 撤销全部订单
     */
    abstract public void revokeAllOrders();

    /**
     * 取消订单
     *
     * @param orderId
     */
    abstract public void cancelOrder(String orderId);

    /**
     * 刷新当前委托 http
     */
    public void refreshCurrentOrders() {
        if (!NetWorkApiManager.getTradeInstance().isOpen()) {
            getCurrentEntrustOrders();
        }
    }


    Map<String, String> sourceMapA = new TreeMap<>(new BookListSort());
    Map<String, String> sourceMapB = new TreeMap<>(new BookListSort());

    public DepthDataBean mergeData(DepthDataBean data) {
        List<List<String>> a = data.getA();
        List<List<String>> b = data.getB();
        String aMax = "0";
        String aMin = "0";
        if (a != null && a.size() > 0) {
            if (a.size() > 100) {
                //控制深度图卖出数据最多一百条
                a = a.subList(0, 100);
                data.setA(a);
            }
            aMax = a.get(a.size() - 1).get(0);
            aMin = a.get(0).get(0);
        }
        float aMinF = new BigDecimal(aMin).floatValue();
        float dValueOfA = new BigDecimal(aMax).subtract(new BigDecimal(aMin)).floatValue();
        String bMax = "0";
        String bMin = "0";
        if (b != null && b.size() > 0) {
            int bSize = b.size();
            if (bSize > 100) {
                //控制深度图买入数据最多一百条
                b = b.subList(bSize - 100, bSize);
                data.setB(b);
            }
            bMax = b.get(b.size() - 1).get(0);
            bMin = b.get(0).get(0);
        }
        float bMaxF = new BigDecimal(bMax).floatValue();
        float dValueOfB = new BigDecimal(bMax).subtract(new BigDecimal(bMin)).floatValue();
        if (dValueOfA > dValueOfB && b.size() > 1) {
            //A 多
            for (int i = a.size() - 1; i >= 0; i--) {
                String priceStr = a.get(i).get(0);
                float price = new BigDecimal(priceStr).floatValue();
                if (price > aMinF + dValueOfB) {
                    a.remove(i);
                }
            }

            //判断是否需要补一根数据
            String priceStr = a.get(a.size() - 1).get(0);
            float price = new BigDecimal(priceStr).floatValue();
            if (price != aMinF + dValueOfB) {
                List<String> aLast = new ArrayList<>();
                aLast.add(String.valueOf(aMinF + dValueOfB));
                aLast.add("0");
                a.add(aLast);
            }

        } else if (dValueOfA < dValueOfB && a.size() > 1) {
            //B 多
            for (int i = b.size() - 1; i >= 0; i--) {
                String priceStr = b.get(i).get(0);
                float price = new BigDecimal(priceStr).floatValue();
                if (price < bMaxF - dValueOfA) {
                    b.remove(i);
                }
            }

            //判断是否需要补一根数据
            String priceStr = b.get(0).get(0);
            float price = new BigDecimal(priceStr).floatValue();
            if (price != aMinF + dValueOfB) {
                List<String> bLast = new ArrayList<>();
                bLast.add(String.valueOf(bMaxF - dValueOfA));
                bLast.add("0");
                b.add(0, bLast);
            }

        }
        return data;

    }


}
